﻿using System;
using System.Collections.ObjectModel;
using Newtonsoft.Json;

namespace FishSimulation.Model {
    [JsonObject(IsReference = true)]
    public class ActorType : ModelBase, IComparable, IComparable<ActorType>, IEquatable<ActorType>
    {
        #region Members
        string _Description, _Name, _FoodValueFormula, _FoodDecrementFormula, _WeightFormula = "1";
        long _LifeSpanMinTicks, _LifeSpanMaxTicks;
        int _MaxLengthInches, _MinLengthInches, _MaxVelocity, _MaxNumberOfOffSpring;
        int _MinTimeToMateDays = 365;
        int _MaxFoodValue = 100;
        string _ImageBase64;
        bool _CanMate, _Checked, _Schools;
        long _WaitToMateTicks;
        System.Windows.Media.SolidColorBrush _Color;
        ObservableCollection<ActorType> _Menu = new ObservableCollection<ActorType>();
        #endregion

        #region Properties
        /// <summary>
        /// True if the organism can reproduce
        /// </summary>
        /// <remarks>True if the organism can reproduce</remarks>
        public bool CanMate {
            get { return _CanMate; }
            set {
                if (_CanMate != value) {
                    _CanMate = value;
                    this.OnPropertyChanged("CanMate");
                }
            }
        }

        public bool IsChecked
        {
            get
            {
                return _Checked;
            }
            set
            {
                if (_Checked != value)
                {
                    _Checked = value;
                    this.OnPropertyChanged("Checked");
                }
            }
        }

        public System.Windows.Media.SolidColorBrush Color {
            get {
                return _Color;
            }
            set {
                if (_Color != value) {
                    _Color = value;
                    this.OnPropertyChanged("Color");
                }
            }
        }

        public string Description {
            get { return _Description; }
            set {
                if (_Description != value) {
                    _Description = value;
                    this.OnPropertyChanged("Description");
                }
            }
        }

        public string FoodDecrementFormula {
            get { return _FoodDecrementFormula; }
            set {
                if (_FoodDecrementFormula != value) {
                    _FoodDecrementFormula = value;
                    this.OnPropertyChanged("FoodDecrementFormula");
                }
            }
        }

        public string FoodValueFormula {
            get { return _FoodValueFormula; }
            set {
                if (_FoodValueFormula != value) {
                    _FoodValueFormula = value;                    
                    this.OnPropertyChanged("FoodValueFormula");
                }
            }
        }
        
        public string ImageBase64 {
            get {
                return _ImageBase64;
            }
            set {
                if (_ImageBase64 != value) {
                    _ImageBase64 = value;
                    this.OnPropertyChanged("ImageBase64");
                }
            }
        }
        
        public long LifeSpanMinTicks 
        {
            get { return _LifeSpanMinTicks; }
            set {
                if (_LifeSpanMinTicks != value)
                {
                    _LifeSpanMinTicks = value;
                    this.OnPropertyChanged("LifeSpanMinTicks");
                }
            }
        }

        public long LifeSpanMaxTicks 
        {
            get { return _LifeSpanMaxTicks; }
            set {
                if (_LifeSpanMaxTicks != value)
                {
                    _LifeSpanMaxTicks = value;
                    this.OnPropertyChanged("LifeSpanMaxTicks");
                }
            }
        }

        public int MaxFoodLevel {
            get { return _MaxFoodValue; }
            set {
                if (_MaxFoodValue != value) {
                    _MaxFoodValue = value;
                    this.OnPropertyChanged("MaxFoodValue");
                }
            }
        }

        public int MaxLengthInches {
            get { return _MaxLengthInches; }
            set {
                if (_MaxLengthInches != value) {
                    _MaxLengthInches = value;
                    this.OnPropertyChanged("MaxLengthInches");
                }
            }
        }

        public int MaxNumberOfOffSpring {
            get {
                return _MaxNumberOfOffSpring;
            }
            set {
                if (_MaxNumberOfOffSpring != value) {
                    _MaxNumberOfOffSpring = value;
                    this.OnPropertyChanged("MaxNumberOfOffSpring");
                }
            }
        }

        public int MaxVelocity {
            get {
                return _MaxVelocity;
            }
            set {
                if (_MaxVelocity != value) {
                    _MaxVelocity = value;
                    this.OnPropertyChanged("MaxVelocity");
                }
            }
        }

        /// <summary>
        /// What other actors can this actor eat?
        /// </summary>
        public ObservableCollection<ActorType> Menu {
            get {
                return _Menu;
            }
            set {
                if (_Menu != value) {
                    _Menu = value;
                    this.OnPropertyChanged("Menu");
                }
            }
        }

        public int MinLengthInches {
            get { return _MinLengthInches; }
            set {
                if (_MinLengthInches != value) {
                    _MinLengthInches = value;
                    this.OnPropertyChanged("MinLengthInches");
                }
            }
        }

        public int MinTimeToMateDays 
        {
            get
            {
                return _MinTimeToMateDays;
            }
            set
            {
                if (_MinTimeToMateDays != value)
                {
                    _MinTimeToMateDays = value;
                    this.OnPropertyChanged("MinTimeToMateDays");
                }
            }
        }

        public string Name {
            get {
                return _Name;
            }
            set {
                if (_Name != value) {
                    _Name = value;
                    this.OnPropertyChanged("Name");
                }
            }
        }

        public bool Schools
        {
            get
            {
                return _Schools;
            }
            set
            {
                if (_Schools != value)
                {
                    _Schools = value;
                    this.OnPropertyChanged("Schools");
                }
            }
        }

        public long WaitToMateTicks {
            get { return _WaitToMateTicks; }
            set {
                if (_WaitToMateTicks != value) {
                    _WaitToMateTicks = value;
                    this.OnPropertyChanged("WaitToMateTicks");
                }
            }
        }

        public string WeightFormula
        {
            get { return _WeightFormula; }
            set
            {
                if (_WeightFormula != value)
                {
                    _WeightFormula = value;
                    this.OnPropertyChanged("WeightFormula");
                }
            }
        }
        #endregion

        #region Methods
        public int CompareTo(object obj) {            
            return this.CompareTo(obj as ActorType);
        }

        public int CompareTo(ActorType other) {
            string n1 = (this.Name ?? "").ToLower().Trim();
            string n2 = null;
            string id1 = (this.Id ?? "").ToLower().Trim();
            string id2 = null;
            if (other != null) {
                n2 = (other.Name ?? "").ToLower().Trim();
                id2 = (other.Id ?? "").ToLower().Trim();
            }
            int i = (n1.CompareTo(n2) == 0 || id1.CompareTo(id2) == 0) ? 0 : 1;
            return i;
        }
        
        public bool Equals(ActorType other) {
            return this.CompareTo(other) == 0;
        }

        public override bool Equals(object obj) {
            return base.Equals(obj);
        }

        public override string ToString() {
            return this.Name;
        }
        #endregion
    }
}
